package gamenetworktest;


public class Game {
    private int myNum; // 1 or 2, whether user attacker number 1 or 2
    public String myName, friendName, D1Name, D2Name;

    private int numOfOurRobots; // Number of our robots
    private int numOfPartnerRobots; // Number of partner's robots
    private int numOfDef1Robots, numOfDef2Robots; // Number of opponent's robots
    private OurRobot[] OurRobots; // Array of our robot objects
    private FriendRobot[] PartnerRobot; //Array of partner's robot objects
    
    //Arrays of defender's robot objects
    private Defender_Robot[] Def1Robots, Def2Robots; 
    
    private Wall_Section[] wallSections; //Array of wall section objects. 
                //First 15 sections belong to left wall, others to right wall 
    private int gold; // Amount of gold owned by the user
    private int turn;
    public boolean ourTurn;

    // mutator method for myNum
    public void set_myNum(int a) {
        myNum = a;
    }

    // accessor for myNum
    public int get_myNum() {
        return myNum;
    }
    
    // accessor for numOfOurRobots
    public int get_numOfOurRobots() {
        return numOfOurRobots;
    }
    
    // accessor for numOfPartnerRobots
    public int get_numOfPartnerRobots() {
        return numOfPartnerRobots;
    }
    
    // accessor for numOfDef1Robots
    public int get_numOfDef1Robots() {
        return numOfDef1Robots;
    }
    
    // accessor for numOfDef2Robots
    public int get_numOfDef2Robots() {
        return numOfDef2Robots;
    }
    
    // accessor for OurRobots[i]
    public OurRobot get_OurRobots(int i) {
        assert (i >= 0);
        if (i >= numOfOurRobots)
            return null;
        return OurRobots[i];
    }
    
    // accessor for PartnerRobot[i]
    public FriendRobot get_PartnerRobot(int i) {
        assert (i >= 0);
        if (i >= numOfPartnerRobots)
            return null;
        return PartnerRobot[i];
    }
    
    // accessor for Def1Robots[i]
    public Defender_Robot get_Def1Robots(int i) {
        assert (i >= 0);
        if (i >= numOfDef1Robots)
            return null;
        return Def1Robots[i];
    }
    
    public void double_gold() {
        gold = gold * 2;
    }
    
    // accessor for Def2Robots[i]
    public Defender_Robot get_Def2Robots(int i) {
        assert ((i >= 0) && (i < numOfDef2Robots));
        return Def2Robots[i];
    }
    
    // accessor for wallSections[i]
    public Wall_Section get_wallSections(int i) {
        assert ((i >= 0) && (i < 30));   
        return wallSections[i];
    }
    
    // accessor for gold
    public int get_gold() {
        return gold;
    }
    
    // accessor for turn
    public int get_turn() {
        return turn;
    }
    
    // Initializes all the attributes at the beginning of the game 
    public  void init(boolean haveFriend, boolean twoDefenders) {
        gold = 10;
        
        if (haveFriend) {
            //numOfOurRobots = 2;
            //numOfPartnerRobots = 2;
            OurRobots = new OurRobot[4];
            PartnerRobot = new FriendRobot[4];
            if (myNum == 1) {
                buildRobot(0, 0, 3);
                buildRobot(0, 0, 11);
                buildRobot(1, 1, 3);
                buildRobot(1, 1, 11);
            }
            else {
                buildRobot(1, 0, 3);
                buildRobot(1, 0, 11);
                buildRobot(0, 1, 3);
                buildRobot(0, 1, 11);
            }
        }
        else {
            //numOfOurRobots = 4;
            //numOfPartnerRobots = 0;
            OurRobots = new OurRobot[8];
            buildRobot(0, 0, 3);
            buildRobot(0, 0, 11);
            buildRobot(0, 1, 3);
            buildRobot(0, 1, 11);
        }
        
        if (twoDefenders) {
           numOfDef1Robots = 2;
           numOfDef2Robots = 2;
           Def1Robots = new Defender_Robot[4];
           Def1Robots[0] = new Defender_Robot(0, 3);
           Def1Robots[1] = new Defender_Robot(0, 11);
           Def2Robots = new Defender_Robot[4];
           Def2Robots[0] = new Defender_Robot(1, 3);
           Def2Robots[1] = new Defender_Robot(1, 11);
        }
        else {
            numOfDef1Robots = 4;
            numOfDef2Robots = 0;
            Def1Robots = new Defender_Robot[8];
            Def1Robots[0] = new Defender_Robot(0, 3);
            Def1Robots[1] = new Defender_Robot(0, 11);
            Def1Robots[2] = new Defender_Robot(1, 3);
            Def1Robots[3] = new Defender_Robot(1, 11);
        }
        
        wallSections = new Wall_Section[30];
        for(int i = 0; i < 30; i++)
            wallSections[i] = new Wall_Section();

        ourTurn = true;
       
    }
    
    //Checks whether given robot can attack specified wall section
    public boolean attack(int robot, int wall, int section) {
        assert ((wall >= 0) && (wall < 2) && (section > 0) && (section < 15));
        assert ((robot >= 0) && (robot < numOfOurRobots));
        
        if (OurRobots[robot].get_posX() != wall) return false;
        if (Math.abs(OurRobots[robot].get_posY() - section) <= 
                                        OurRobots[robot].get_range())
            
            return true;
        
        return false;
    }
    
    //Checks whether given robot can move to specified place
    public boolean move(int robot, int posX, int posY) {
        assert ((posX >= 0) && (posX < 2) && (posY > 0) && (posY < 15));
        assert ((robot >= 0) && (robot < numOfOurRobots));

        for(int i = 0; i < get_numOfOurRobots(); i++)
            if((OurRobots[i].get_posX() == posX) &&
                        (OurRobots[i].get_posY() == posY))
                return false;

        for(int i = 0; i < get_numOfPartnerRobots(); i++)
            if((PartnerRobot[i].get_posX() == posX) &&
                        (PartnerRobot[i].get_posY() == posY))
                return false;
        
        if(Math.abs(OurRobots[robot].get_posX() - posX) + 
                Math.abs(OurRobots[robot].get_posY() - posY) <= 
                    OurRobots[robot].get_speed())
            return true;
        
        return false;
    }
    
    //Creates new robot
    //Creates robot based on robotType
    //0: Our Robot; 1: Friend Robot; 2: Defender 1; 3: Defender 2 robot
    // retuns false, if cannot build
    public boolean buildRobot(int robotType, int x , int y) {
        assert ((x >= 0) && (x < 2) && (y > 0) && (y < 15));
        assert ((robotType >= 0) && (robotType <= 3));
                
        switch (robotType) {
            case 0: 
                if(numOfOurRobots == OurRobots.length - 1) return false;
                OurRobots[numOfOurRobots++] = new OurRobot(x, y);

            break;
            case 1:
                PartnerRobot[numOfPartnerRobots++] = new FriendRobot(x, y);
            break;
            case 2:
                Def1Robots[numOfDef1Robots++] = new Defender_Robot(x, y);
            break;
            case 3:
                Def2Robots[numOfDef2Robots++] = new Defender_Robot(x, y);
            break;
        }
        return true;
    }

    //
    public boolean buyRobot(int posX, int posY) {
        assert ((posX >= 0) && (posX < 2) && (posY > 0) && (posY < 15));
        
        for(int i = 0; i < get_numOfOurRobots(); i++)
            if((OurRobots[i].get_posX() == posX) &&
                        (OurRobots[i].get_posY() == posY))
                return false;

        for(int i = 0; i < get_numOfPartnerRobots(); i++)
            if((PartnerRobot[i].get_posX() == posX) &&
                        (PartnerRobot[i].get_posY() == posY))
                return false;

        if(gold < 50) return false;

        gold = gold - 50;
        
        return true;
    }
    
    // Upgrades given robot to the next level, 
    // if the robot is not at maximum level, and amount of owned gold is enough. 
    // Returns false, if cannot upgrade, true otherwise.
    public boolean upgradePower(int robot) {
        if((OurRobots[robot].get_powerLevel() == 0) && (gold >= 20)) {
            OurRobots[robot].upgradePower();
            gold = gold - 20;
            return true;
        }
        else if((OurRobots[robot].get_powerLevel() == 1) && (gold >= 40)) {
            OurRobots[robot].upgradePower();
            gold = gold - 40;
            return true;
        }
        else if((OurRobots[robot].get_powerLevel() == 2) && (gold >= 60)) {
            OurRobots[robot].upgradePower();
            gold = gold - 60;
            return true;
        }
           
        return false;
    }
    
    public boolean upgradeSpeed(int robot) {
        if((OurRobots[robot].get_speedLevel() == 0) && (gold >= 15)) {
            OurRobots[robot].upgradeSpeed();
            gold = gold - 15;
            return true;
        }
        else if((OurRobots[robot].get_speedLevel() == 1) && (gold >= 20)) {
            OurRobots[robot].upgradeSpeed();
            gold = gold - 20;
            return true;
        }
        else if((OurRobots[robot].get_speedLevel() == 2) && (gold >= 25)) {
            OurRobots[robot].upgradeSpeed();
            gold = gold - 25;
            return true;
        }
        else if((OurRobots[robot].get_speedLevel() == 3) && (gold >= 30)) {
            OurRobots[robot].upgradeSpeed();
            gold = gold - 30;
            return true;
        }
           
        return false;
    }
    
    public boolean upgradeRange(int robot) {
        if((OurRobots[robot].get_rangeLevel() == 0) && (gold >= 15)) {
            OurRobots[robot].upgradeRange();
            gold = gold - 15;
            return true;
        }
        else if((OurRobots[robot].get_rangeLevel() == 1) && (gold >= 20)) {
            OurRobots[robot].upgradeRange();
            gold = gold - 20;
            return true;
        }
        else if((OurRobots[robot].get_rangeLevel() == 2) && (gold >= 25)) {
            OurRobots[robot].upgradeRange();
            gold = gold - 25;
            return true;
        }
        else if((OurRobots[robot].get_rangeLevel() == 3) && (gold >= 30)) {
            OurRobots[robot].upgradeRange();
            gold = gold - 30;
            return true;
        }
           
        return false;
    }
    
    // Increments turn, resets gold amount
    public void finishTurn() {
        if (!ourTurn) {
            turn++;
            ourTurn = true;
        }
        else ourTurn = false;
        
        if(turn < 5) gold = gold + 10;
        else if (turn < 10) gold = gold + 20;
        else gold = gold + 40;
    }
    
}
